<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
    </style>
</head>

<body>
    <div id="test">
        <div id="box">abc</div>
    </div>
    <script>
        const divEl = document.querySelector("#test")
        const boxEl = document.querySelector("#box")
        const ulEl = document.createElement('ul')
        ulEl.innerText = '123456'
        boxEl.insertBefore(ulEl, undefined)

        function patchKeyedChildren(c1, c2, container, anchor) {
            const map = new Map()
            c1.forEach((prev, j) => {
                map.set(prev.key, { prev, j })
            })
            let maxNewIndexSoFar = 0
            // 遍历新的子节点
            for (let i = 0; i < c2.length; i++) {
                const next = c2[i]

                if (map.has(next.key)) {
                    const { prev, j } = map.get(next.key)
                    patch(prev, next, container, anchor)
                    // const curAnchor = c1[0].el
                    // const curAnchor = c2[i - 1].el.nextSibling
                    // 把旧的子节点插到第一个位置，第一次的时候curAnchor是旧的第一个DOM

                    // diff算法移动的条件：在旧DOM列表中寻找当前节点的引用，如果他的索引大于当前的maxIndex,不需要移动这个DOM，要把这个索引设置为当前maxIndex
                    // 如果在旧DOM的索引小于当前的maxIndex就要移动
                    // 升序不需要移动
                    if (j < maxNewIndexSoFar) {
                        // 需要移动
                        const curAnchor = c2[i - 1].el.nextSibling
                        container.insertBefore(next.el, curAnchor)
                    } else {
                        maxNewIndexSoFar = j
                    }

                    // 如果找到了就把这个节点从map中移除，剩下的都是新DOM中没有的
                    map.delete(next.key)
                } else {
                    // 拿到当前这个新增的DOM，然后进行插入
                    const curAnchor = i === 0 ? c1[0].el : c2[i - 1].el.nextSibling
                    patch(null, next, container, curAnchor)
                }

            }

            // 这层遍历是为了把旧DOM中有 新DOM中没有的节点去除
            map.forEach(({ prev }) => {
                unmount(prev)
            })

        }
    </script>
</body>

</html>